package util;

import visu.Positionnable;

/**
 * Classe utilitaire pour des calculs de distance et de direction.
 * 
 * @author COLLET Philippe
 * @author gnpt
 */
public class DistancesEtDirections {

	/**
	 * Permet de trouver la distance en pixels entre deux points (x0, y0) et
	 * (x1, y1).
	 * 
	 * @param x0
	 *            l'abscisse du premier point.
	 * @param y0
	 *            l'ordonnée du premier point.
	 * @param x1
	 *            l'abscisse du second point.
	 * @param y1
	 *            l'ordonnée du second point.
	 * @return la distance en pixels entre (x0, y0) et (x1, y1).
	 */
	public static float distanceDepuisUnPoint(int x0, int y0, int x1, int y1) {
		// rend la distance entre la bêbète et un point donné
		return (float) Math.sqrt(Math.pow(x1 - x0, 2) + Math.pow(y1 - y0, 2));
	}

	/**
	 * Permet de trouver l'angle en radians (entre ]-PI, PI[) de l'objet
	 * positionnable p, par rapport à un point origine et à l'axe donné.
	 * 
	 * @param p
	 *            l'entité positionnable.
	 * @param xOrigine
	 *            l'abscisse du point d'origine.
	 * @param yOrigine
	 *            l'ordonnée du point d'origine.
	 * @param axe
	 *            l'axe donné.
	 * @return l'angle en radians (entre ]-PI, PI[) de l'objet positionnable p,
	 *         par rapport à un point origine et à l'axe donné.
	 */
	public static float directionDepuisUnPoint(Positionnable p, int xOrigine,
			int yOrigine, float axe) {
		// tan x = coté opposé / coté adjacent
		float angle;
		int x = p.getX();
		int y = p.getY();

		if (x == xOrigine && y == yOrigine) {
			// Les deux entités sont sur la même case, la direction n'est pas
			// définie
			return Float.NaN;
		}
		if (x != xOrigine)
			angle = (float) Math.atan((y - yOrigine) / (x - xOrigine));
		else if (y < yOrigine)
			angle = -(float) (Math.PI / 2);
		else
			angle = (float) (Math.PI / 2);
		// atan a deux solutions, donc il faut corriger...
		if (x < xOrigine) {
			if (y < yOrigine)
				angle -= (float) Math.PI;
			else
				angle += (float) Math.PI;
		}
		// Il suffit maintenant de soustraire l'axe à la direction (en radians)
		// et obtenir une direction entre -PI et PI
		float dir = angle - axe;

		if (dir >= (float) Math.PI)
			return dir - (float) (Math.PI * 2);
		else if (dir < -(float) Math.PI)
			return dir + (float) (Math.PI * 2);
		else
			return dir;
	}
}
